package main
import (
	"log"
	"net"
	"../logger"
	"strings"
	"time"
	"io"
	"encoding/binary"
)


func main() {
	logger.INFO("server initialized")
	defer func() {
		if x := recover(); x != nil {
			logger.ERR("Caught panic in main()", x)
		}
	}()

	start_up()

	tcpAddr, err := net.ResolveTCPAddr("tcp4", ":9090")
	checkError(err)

	listener, err := net.ListenTCP("tcp", tcpAddr)
	checkError(err)

	for {
		conn, err := listener.AcceptTCP()
		if err != nil {
			logger.WARN("Error to listener TCP", conn)
			continue;
		}

		go handleConnect(conn)
	}
}

func handleConnect(conn *net.TCPConn) {

	if x := recover(); x != nil {
		logger.ERR("Caught panic in handleConnect():", x)
	}

	header := make([]byte, _DEFAULT_HEADER_SIZE)
	in := make(chan []byte, _DEFAULT_INQUEUE_SIZE)
	bufctrl := make(chan bool)

	defer func() {
		close(bufctrl)
		close(in)
	}()

	var sess Session
	sess.IP = net.ParseIP(strings.Split(conn.RemoteAddr().String(), ":")[0])
	logger.NOTICE("New connect from:", sess.IP)

	out := NewBuffer(&sess, conn, bufctrl)
	go out.Start()

	wg.Add(1)
	go StartMouse(&sess, in, out)

	for {
		conn.SetReadDeadline(time.Now().Add(_TCP_TIMEOUT * time.Second))
		n, err := io.ReadFull(conn, header)

		if err != nil {
			logger.WARN("error receive msg: bytes", n, "err:", err)
			break
		}

		size := binary.BigEndian.Uint16(header)

		data := make([]byte, size)
		n, err = io.ReadFull(conn, data)
		if err != nil {
			logger.WARN("error receive msg, bytes:", n, "reason:", err)
			break
		}

		select {
		case in <- data:
		case <-time.After(_MAX_DELAY_IN * time.Second):
			logger.WARN("server busy or agent closed, session flag:", sess.Flag)
			return
		}
	}
}

func checkError(err error) {
	if err != nil {
		log.Fatal("handle error:", err)
	}
}